package com.sinosoft.common.core.redis;


import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

import javax.annotation.PostConstruct;
import java.util.*;

/**
 * 操作Redis的类
 * 
 * @author liuxiao
 *
 */
@Slf4j
@Component
public class RedisUtil {

    @Value("${redis.host}")
    private String host;

    @Value("${redis.password}")
    private String password;

    @Value("${redis.port}")
    private Integer port;

    @Value("${redis.maxInst}")
    private Integer maxInst;

    @Value("${redis.maxIdle}")
    private Integer maxIdle;

    @Value("${redis.maxWait}")
    private Integer maxWait;

	@Value("${redis.database}")
	private Integer database;

    private static JedisPool jedisPool;
    private JedisPoolConfig conf = new JedisPoolConfig();

    private RedisUtil() {
    }

    @PostConstruct
    private void init() {
        conf.setMaxTotal(maxInst);
        conf.setMaxIdle(maxIdle);
        conf.setMaxWaitMillis(maxWait);
        conf.setTestOnBorrow(true);
        createJedisPool();
    }

    private void createJedisPool() {
        try {
        	System.out.println(host);
            if (jedisPool == null || (jedisPool != null && jedisPool.isClosed())) {
                jedisPool = new JedisPool(conf, host, port, 2000, password,database);
            }
        } catch (Exception e) {
            log.error("can not create JedisPool.", e);
        }
    }

    /**
     * 获取Jedis连接
     * 
     * @return
     */
    public static Jedis getConnection() {
        Jedis jedis = null;
        if (jedisPool != null && !jedisPool.isClosed()) {
            try {
                jedis = jedisPool.getResource();
            } catch (Exception e) {
                close(jedis);
                log.error("can not get jedis from JedisPool.", e);
            }
        } else {
            log.error("JedisPool is closed!");
            throw new RuntimeException("JedisPool is closed!");
        }
        return jedis;
    }

    /**
     * 关闭Jedis连接
     * 
     * @param jedis
     */
    public static void close(Jedis jedis) {
        if (jedis != null) {
            try {
                jedis.close();
            } catch (Exception e) {
                log.error("can not return jedis to JedisPool.", e);
            }
        }
    }
    
    
    /**
	 * 从Redis上获取数据
	 * 
	 * <pre>
	 * &#64;param key
	 * &#64;return
	 * Modifications:
	 * Modifier wangdefeng; 2017年4月21日; Create new Method getStringFromRedis
	 * </pre>
	 */
	public static String getStringFromRedis(String key) {
		Jedis jedis = null;
		String result = null;
		try {
			jedis = RedisUtil.getConnection();
			result = jedis.get(key);
		} catch (Exception e) {
			e.printStackTrace();
			log.error(e.getMessage(), e);
		} finally {
			if (jedis != null) {
				RedisUtil.close(jedis);
			}
		}
		return result;
	}
    
	/**
	 * 向redis存数据
	 * 
	 * <pre>
	 * &#64;param key
	 * &#64;param value
	 * Modifications:
	 * Modifier wangdefeng; 2017年4月21日; Create new Method putStringToRedis
	 * </pre>
	 */
	public static void setCacheObject(String key, String value) {
		Jedis jedis = null;
		try {
			jedis = RedisUtil.getConnection();
			jedis.set(key, value);
			jedis.expire(key, getExpireSecond());
		} catch (Exception e) {
			e.printStackTrace();
			log.error(e.getMessage(), e);
		} finally {
			if (null != jedis) {
				RedisUtil.close(jedis);
			}
		}
	}

	/**
	 * 指定时间缓存数据
	 * @Author renjm
	 * @Date 2019/12/29 0029 下午 15:04
	 * @Description
	 * @param key
	 * @param value
	 * @param expireTimeVal 单位：秒，为0时永久
	 * @return void
	 **/
	public static void putStringToRedis(String key, String value, int expireTimeVal) {
		Jedis jedis = null;
		try {
			jedis = RedisUtil.getConnection();
			jedis.set(key, value);
			// 失效时间单位:秒
			if (expireTimeVal != 0) {
				jedis.expire(key, expireTimeVal);
			}
		} catch (Exception e) {
			e.printStackTrace();
			log.error(e.getMessage(), e);
		} finally {
			if (null != jedis) {
				RedisUtil.close(jedis);
			}
		}
	}
	
	/**
	 * 添加数据到redis
	 * @param key
	 * 			key
	 * @param value
	 * 			value
	 * @param expire
	 * 			过期时间
	 */
	public static void setCacheObject(String key, String value,int expire) {
		Jedis jedis = null;
		try {
			jedis = RedisUtil.getConnection();
			jedis.set(key, value);
			jedis.expire(key, expire);
		} catch (Exception e) {
			e.printStackTrace();
			log.error(e.getMessage(), e);
		} finally {
			if (null != jedis) {
				RedisUtil.close(jedis);
			}
		}
	}
	
	/**
	 * 根据redis的key和map中的key获取value
	 * @param key
	 * @param field
	 * @return
	 */
	public List<String> getMapValueByKeyFromRedis(String key,String field){
		Jedis jedis = null;
		List<String> result = null;
		try {
			jedis = RedisUtil.getConnection();
			result = jedis.hmget(key,field);
		} catch (Exception e) {
			e.printStackTrace();
			log.error(e.getMessage(), e);
		} finally {
			if (jedis != null) {
				RedisUtil.close(jedis);
			}
		}
		return result;
	}
	/**
	 * 获取map中所有的key
	 * @param key
	 * @return
	 */
	public Set<String> getMapKeyFromRedis(String key){
		Jedis jedis = null;
		Set<String> result = null;
		try {
			jedis = RedisUtil.getConnection();
			result = jedis.hkeys(key);
		} catch (Exception e) {
			e.printStackTrace();
			log.error(e.getMessage(), e);
		} finally {
			if (jedis != null) {
				RedisUtil.close(jedis);
			}
		}
		return result;
	}
	
	/**
	 * 将map缓存到redis中
	 * @param key
	 * @param map
	 */
	public  void putMapToRedis(String key,Map map){
		Jedis jedis = null;
		try {
			jedis = RedisUtil.getConnection();
			jedis.hmset(key, map);
			jedis.expire(key, getExpireSecond());
		} catch (Exception e) {
			e.printStackTrace();
			log.error(e.getMessage(), e);
		} finally {
			if (null != jedis) {
				RedisUtil.close(jedis);
			}
		}
	}
	/**
	 * 获取到当天24点剩余时间，单位（s）
	 * 
	 * <pre>
	 * &#64;return
	 * Modifications:
	 * Modifier wangdefeng; 2017年4月21日; Create new Method getExpireSecond
	 * </pre>
	 */
	private static int getExpireSecond() {
		Date date = new Date();
		Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		cal.set(Calendar.HOUR, 0);
		cal.set(Calendar.MINUTE, 0);
		cal.set(Calendar.SECOND, 0);
		cal.set(Calendar.MILLISECOND, 0);
		cal.add(Calendar.DATE, 1);
		Date nextDate = cal.getTime();
		return (int) (nextDate.getTime() - date.getTime()) / 1000;
	}
	
	/**
	 * 删除redis数据
	 * @param key
	 * @return
	 */
	public static void deleteObject(String key) {
		Jedis jedis = null;
		try {
			jedis = RedisUtil.getConnection();
			jedis.del(key);
		} catch (Exception e) {
			e.printStackTrace();
			log.error(e.getMessage(), e);
		} finally {
			if (jedis != null) {
				RedisUtil.close(jedis);
			}
		}
	}

	/**
	 * 判断key是否存在
	 * @param key
	 * @return
	 */
	public static boolean hasKey(String key) {
		Jedis jedis = null;
		Boolean exists = false;
		try {
			jedis = RedisUtil.getConnection();
			exists = jedis.exists(key);
		} catch (Exception e) {
			e.printStackTrace();
			log.error(e.getMessage(), e);
		} finally {
			RedisUtil.close(jedis);
		}
		return exists;
	}

	/**
	 * 获得缓存的基本对象列表
	 * pattern 字符串前缀
	 * @return
	 */
	public static Collection<String> keys(String pattern) {
		Jedis jedis = null;
		Collection<String> result = null;
		try {
			jedis = RedisUtil.getConnection();
			result = jedis.keys(pattern);
		} catch (Exception e) {
			e.printStackTrace();
			log.error(e.getMessage(), e);
		} finally {
			RedisUtil.close(jedis);
		}
		return result;
	}

	/**
	 * 删除集合对象
	 *
	 * @param collection 多个对象
	 * @return
	 */
	public static void deleteObject(Collection collection) {
		Jedis jedis = null;
		try {
			jedis = RedisUtil.getConnection();
			Iterator iterator = collection.iterator();
			while (iterator.hasNext()) {
				jedis.del(iterator.next().toString());
			}
		} catch (Exception e) {
			e.printStackTrace();
			log.error(e.getMessage(), e);
		} finally {
			if (jedis != null) {
				RedisUtil.close(jedis);
			}
		}
	}

}
